from fastapi import Request
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List
from config.constant import CommonConstant
from exceptions.exception import ServiceException
from module_admin.entity.vo.common_vo import CrudResponseModel
from module_admin.service.dict_service import DictDataService
from module_rag.dao.doc_dao import DocDao
from module_rag.entity.vo.doc_vo import DeleteDocModel, DocModel, DocPageQueryModel
from utils.common_util import CamelCaseUtil
from utils.excel_util import ExcelUtil
from utils.page_util import PageResponseModel
from utils.minio_util import download_file_from_minio
from utils.ai_util import import_chromadb
import os
class DocService:
    """
    知识库附属文档信息模块服务层
    """

    #@classmethod
    # async def solve_doc_services(doc_detail):
    #     #拿到临时文件地址
    #     doc_id = doc_detail.doc_id
    #     file_name = doc_detail.file_name
    #     file_path = download_file_from_minio(file_name=file_name)
    #     #向量数据库存储
    #     try:
    #         res = import_chromadb(doc_id,file_path)
    #          #删除临时文件
    #         os.remove(file_path)
    #         return res  
    #     except Exception as e:
    #         raise ServiceException(message='向量数据库存储失败')
    

    @classmethod
    async def get_doc_list_services(
        cls, query_db: AsyncSession, query_object: DocPageQueryModel, is_page: bool = False
    ):
        """
        获取知识库附属文档信息列表信息service

        :param query_db: orm对象
        :param query_object: 查询参数对象
        :param is_page: 是否开启分页
        :return: 知识库附属文档信息列表信息对象
        """
        query_result = await DocDao.get_doc_list(query_db, query_object, is_page)
        if is_page:
            doc_list_result = PageResponseModel(
                **{
                    **query_result.model_dump(by_alias=True),
                    'rows': [{**row[0], 'rag':row[1],'user':row[2]} for row in query_result.rows],
                }
            )
        else:
            doc_list_result = []
            if query_result:
                doc_list_result = [{**row[0], 'rag':row[1],'user':row[2]} for row in query_result]


        return doc_list_result


    @classmethod
    async def add_doc_services(cls, query_db: AsyncSession, page_object: DocModel):
        """
        新增知识库附属文档信息信息service

        :param query_db: orm对象
        :param page_object: 新增知识库附属文档信息对象
        :return: 新增知识库附属文档信息校验结果
        """
        try:
            await DocDao.add_doc_dao(query_db, page_object)
            await query_db.commit()
            return CrudResponseModel(is_success=True, message='新增成功')
        except Exception as e:
            await query_db.rollback()
            raise e

    @classmethod
    async def edit_doc_services(cls, query_db: AsyncSession, page_object: DocModel):
        """
        编辑知识库附属文档信息信息service

        :param query_db: orm对象
        :param page_object: 编辑知识库附属文档信息对象
        :return: 编辑知识库附属文档信息校验结果
        """
        edit_doc = page_object.model_dump(exclude_unset=True, exclude={})
        doc_info = await cls.doc_detail_services(query_db, page_object.doc_id)
        if doc_info.doc_id:
            try:
                await DocDao.edit_doc_dao(query_db, edit_doc)
                await query_db.commit()
                return CrudResponseModel(is_success=True, message='更新成功')
            except Exception as e:
                await query_db.rollback()
                raise e
        else:
            raise ServiceException(message='知识库附属文档信息不存在')

    @classmethod
    async def delete_doc_services(cls, query_db: AsyncSession, page_object: DeleteDocModel):
        """
        删除知识库附属文档信息信息service

        :param query_db: orm对象
        :param page_object: 删除知识库附属文档信息对象
        :return: 删除知识库附属文档信息校验结果
        """
        if page_object.doc_ids:
            doc_id_list = page_object.doc_ids.split(',')
            try:
                for doc_id in doc_id_list:
                    await DocDao.delete_doc_dao(query_db, DocModel(docId=doc_id))
                await query_db.commit()
                return CrudResponseModel(is_success=True, message='删除成功')
            except Exception as e:
                await query_db.rollback()
                raise e
        else:
            raise ServiceException(message='传入文档标题为空')

    @classmethod
    async def doc_detail_services(cls, query_db: AsyncSession, doc_id: int):
        """
        获取知识库附属文档信息详细信息service

        :param query_db: orm对象
        :param doc_id: 文档标题
        :return: 文档标题对应的信息
        """
        doc = await DocDao.get_doc_detail_by_id(query_db, doc_id=doc_id)
        if doc:
            result = DocModel(**CamelCaseUtil.transform_result(doc))
        else:
            result = DocModel(**dict())

        return result

    @staticmethod
    async def export_doc_list_services(request: Request, doc_list: List):
        """
        导出知识库附属文档信息信息service

        :param doc_list: 知识库附属文档信息信息列表
        :return: 知识库附属文档信息信息对应excel的二进制数据
        """
        # 创建一个映射字典，将英文键映射到中文键
        mapping_dict = {
            'docId': '文档标题',
            'ragId': '知识库id',
            'userId': '用户id',
            'docName': '文档名称',
            'type': '文档类型',
            'author': '作者',
            'remoteUrl': 'minio地址',
            'serectLevel': '保密等级',
            'status': '状态',
            'createDate': '上传日期',
        }
        bjj_rag_doc_status_list = await DictDataService.query_dict_data_list_from_cache_services(
            request.app.state.redis, dict_type='bjj_rag_doc_status'
        )
        bjj_rag_doc_status_option = [dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in bjj_rag_doc_status_list]
        bjj_rag_doc_status_option_dict = {item.get('value'): item for item in bjj_rag_doc_status_option}
        bjj_rag_doc_secret_level_list = await DictDataService.query_dict_data_list_from_cache_services(
            request.app.state.redis, dict_type='bjj_rag_doc_secret_level'
        )
        bjj_rag_doc_secret_level_option = [dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in bjj_rag_doc_secret_level_list]
        bjj_rag_doc_secret_level_option_dict = {item.get('value'): item for item in bjj_rag_doc_secret_level_option}
        bjj_rag_doc_type_list = await DictDataService.query_dict_data_list_from_cache_services(
            request.app.state.redis, dict_type='bjj_rag_doc_type'
        )
        bjj_rag_doc_type_option = [dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in bjj_rag_doc_type_list]
        bjj_rag_doc_type_option_dict = {item.get('value'): item for item in bjj_rag_doc_type_option}
        for item in doc_list:
            if str(item.get('type')) in bjj_rag_doc_type_option_dict.keys():
                item['type'] = bjj_rag_doc_type_option_dict.get(str(item.get('type'))).get('label')
            if str(item.get('serectLevel')) in bjj_rag_doc_secret_level_option_dict.keys():
                item['serectLevel'] = bjj_rag_doc_secret_level_option_dict.get(str(item.get('serectLevel'))).get('label')
            if str(item.get('status')) in bjj_rag_doc_status_option_dict.keys():
                item['status'] = bjj_rag_doc_status_option_dict.get(str(item.get('status'))).get('label')
        binary_data = ExcelUtil.export_list2excel(doc_list, mapping_dict)

        return binary_data
